Skip to content

Conversation

@TonyHan11
Copy link
Contributor

The purpose of this PR is to update sam_gmac driver from supporting only one instance to supporting multiple instances.

The following two files are updated:

  • drivers/ethernet/eth_sam_gmac.c
  • drivers/ethernet/eth_sam_gmac_priv.h

Changes include:

  • centralize the lists used for different GMAC queues
  • add instance and num_queues to configuration
  • update for supporting multi GMAC instances

Comment on lines 267 to 269
uint32_t instance:8;
uint32_t num_queues:8;
uint32_t reserved:16;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why bitfields instead of one uint16_t and two uint8_t?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No special reasons for using bitfields just it's easier to keep the structure word aligned.
Will be updated with uint16_t and uint8_t, thanks.

#endif
#define SAM_GMAC_CFG_DEFN(n) \
static const struct eth_sam_dev_cfg eth##n##_config = { \
.instance = n, \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems only to be used for logging, maybe use dev->name instead. That's how it's done at other drivers

Comment on lines 2105 to 2108
#if NODE_HAS_VALID_MAC_ADDR(DT_DRV_INST(n))
#define DEFN_DATA_MAC_ADDR(n) .mac_addr = DT_INST_PROP(n, local_mac_address),
#else
#define DEFN_DATA_MAC_ADDR(n)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use DT_INST_PROP_OR(n, local_mac_address, {0}) instead

Comment on lines 139 to 188
#define DEFN_RX_DESC(n) \
static struct gmac_desc rx_desc##n##_que[PRIORITY_QUEUE_RX_DESC_COUNT] \
__nocache __aligned(GMAC_DESC_ALIGNMENT);
DT_INST_FOREACH_STATUS_OKAY(DEFN_RX_DESC)

/* TX descriptors list */
static struct gmac_desc tx_desc_que0[MAIN_QUEUE_TX_DESC_COUNT]
__nocache __aligned(GMAC_DESC_ALIGNMENT);
#if GMAC_PRIORITY_QUEUE_NUM >= 1
static struct gmac_desc tx_desc_que1[PRIORITY_QUEUE1_TX_DESC_COUNT]
__nocache __aligned(GMAC_DESC_ALIGNMENT);
#endif
#if GMAC_PRIORITY_QUEUE_NUM >= 2
static struct gmac_desc tx_desc_que2[PRIORITY_QUEUE2_TX_DESC_COUNT]
__nocache __aligned(GMAC_DESC_ALIGNMENT);
#endif
#if GMAC_PRIORITY_QUEUE_NUM >= 3
static struct gmac_desc tx_desc_que3[PRIORITY_QUEUE3_TX_DESC_COUNT]
__nocache __aligned(GMAC_DESC_ALIGNMENT);
#endif
#if GMAC_PRIORITY_QUEUE_NUM >= 4
static struct gmac_desc tx_desc_que4[PRIORITY_QUEUE4_TX_DESC_COUNT]
__nocache __aligned(GMAC_DESC_ALIGNMENT);
#endif
#if GMAC_PRIORITY_QUEUE_NUM >= 5
static struct gmac_desc tx_desc_que5[PRIORITY_QUEUE5_TX_DESC_COUNT]
__nocache __aligned(GMAC_DESC_ALIGNMENT);
#endif
#define DEFN_TX_DESC(n) \
static struct gmac_desc tx_desc##n##_que[PRIORITY_QUEUE_TX_DESC_COUNT] \
__nocache __aligned(GMAC_DESC_ALIGNMENT);
DT_INST_FOREACH_STATUS_OKAY(DEFN_TX_DESC)

/* RX buffer accounting list */
static struct net_buf *rx_frag_list_que0[MAIN_QUEUE_RX_DESC_COUNT];
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 1
static struct net_buf *rx_frag_list_que1[PRIORITY_QUEUE1_RX_DESC_COUNT];
#endif
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 2
static struct net_buf *rx_frag_list_que2[PRIORITY_QUEUE2_RX_DESC_COUNT];
#endif
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 3
static struct net_buf *rx_frag_list_que3[PRIORITY_QUEUE3_RX_DESC_COUNT];
#endif
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 4
static struct net_buf *rx_frag_list_que4[PRIORITY_QUEUE4_RX_DESC_COUNT];
#endif
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 5
static struct net_buf *rx_frag_list_que5[PRIORITY_QUEUE5_RX_DESC_COUNT];
#endif
#define DEFN_RX_FRAG(n) \
static struct net_buf *rx_frag_list##n##_que[PRIORITY_QUEUE_RX_DESC_COUNT];
DT_INST_FOREACH_STATUS_OKAY(DEFN_RX_FRAG)

#if GMAC_MULTIPLE_TX_PACKETS == 1
/* TX buffer accounting list */
static struct net_buf *tx_frag_list_que0[MAIN_QUEUE_TX_DESC_COUNT];
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 1
static struct net_buf *tx_frag_list_que1[PRIORITY_QUEUE1_TX_DESC_COUNT];
#endif
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 2
static struct net_buf *tx_frag_list_que2[PRIORITY_QUEUE2_TX_DESC_COUNT];
#endif
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 3
static struct net_buf *tx_frag_list_que3[PRIORITY_QUEUE3_TX_DESC_COUNT];
#endif
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 4
static struct net_buf *tx_frag_list_que4[PRIORITY_QUEUE4_TX_DESC_COUNT];
#endif
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 5
static struct net_buf *tx_frag_list_que5[PRIORITY_QUEUE5_TX_DESC_COUNT];
#endif
#define DEFN_TX_FRAG(n) \
static struct net_buf *tx_frag_list##n##_que[PRIORITY_QUEUE_TX_DESC_COUNT];
DT_INST_FOREACH_STATUS_OKAY(DEFN_TX_FRAG)

#if defined(CONFIG_PTP_CLOCK_SAM_GMAC)
#if defined(CONFIG_PTP_CLOCK_SAM_GMAC)
#define NET_PKT_PER_QUE (CONFIG_NET_PKT_TX_COUNT + 1)
/* TX frames accounting list */
static struct net_pkt *tx_frame_list_que0[CONFIG_NET_PKT_TX_COUNT + 1];
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 1
static struct net_pkt *tx_frame_list_que1[CONFIG_NET_PKT_TX_COUNT + 1];
#endif
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 2
static struct net_pkt *tx_frame_list_que2[CONFIG_NET_PKT_TX_COUNT + 1];
#endif
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 3
static struct net_pkt *tx_frame_list_que3[CONFIG_NET_PKT_TX_COUNT + 1];
#endif
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 4
static struct net_pkt *tx_frame_list_que4[CONFIG_NET_PKT_TX_COUNT + 1];
#endif
#if GMAC_ACTIVE_PRIORITY_QUEUE_NUM >= 5
static struct net_pkt *tx_frame_list_que5[CONFIG_NET_PKT_TX_COUNT + 1];
#endif
#endif
#endif
#define DEFN_TX_FRAME(n) \
static struct net_pkt *tx_frame_list##n##_que[NET_PKT_PER_QUE * \
(GMAC_ACTIVE_PRIORITY_QUEUE_NUM + 1)];
DT_INST_FOREACH_STATUS_OKAY(DEFN_TX_FRAME)
#endif /* CONFIG_PTP_CLOCK_SAM_GMAC */
#endif /* GMAC_MULTIPLE_TX_PACKETS */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move these in the DT_INST_FOREACH_STATUS_OKAY at the end

DEVICE_DEFINE(gmac_ptp_clock_##n, PTP_CLOCK_NAME, ptp_gmac_##n##_init, \
NULL, &ptp_gmac_##n##_context, NULL, POST_KERNEL, \
CONFIG_PTP_CLOCK_INIT_PRIORITY, &ptp_api);
DT_INST_FOREACH_STATUS_OKAY(SAM_GMAC_PTP_CLOCK_DEFN)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please only do DT_INST_FOREACH_STATUS_OKAY() one per driver


/* The rest of initialization should only be done once */
if (init_done) {
if (dev_data->init_done) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if dev_data->iface is no longer NULL iface init was done, no need to have a seperate var in dev_data

struct eth_sam_dev_data *const dev_data = dev->data;
int retval;

dev_data->link_up = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's part of a staric struct, its initial value is 0 / false.
also dev_data->link_up seems unnecessary, as the phy is responsible for not notifying the ethernet driver multiple times. dev_data->link_up can be removed IMO


/* Device constant configuration parameters */
struct eth_sam_dev_cfg {
uint32_t instance:8;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line 34: #define GMAC_QUEUE_NUM DT_INST_PROP(0, num_queues)
still uses the first instance, it should not, as it is used for the other instances too

#endif
#endif /* !CONFIG_NET_TEST */

BUILD_ASSERT(DT_INST_ENUM_IDX(0, phy_connection_type) <= 1, "Invalid PHY connection");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here


dev_data->link_up = false;
dev_data->init_done = false;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line 1663. #if DT_INST_NODE_HAS_PROP(0, mac_eeprom) too
and line 1668

#endif
#define DEFN_TX_FRAME(n) \
static struct net_pkt *tx_frame_list##n##_que[NET_PKT_PER_QUE * \
(GMAC_ACTIVE_PRIORITY_QUEUE_NUM + 1)];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line 1006: switch (DT_INST_ENUM_IDX(0, phy_connection_type)) { too

@fabiobaltieri
Copy link
Member

Hey, this needs a rebase and force push to pick up the CI error workaround.

@TonyHan11 TonyHan11 force-pushed the gmac_multi_instance branch from e667bf9 to 2f68375 Compare June 5, 2025 09:16
@TonyHan11
Copy link
Contributor Author

@maass-hamburg
Thank you for your comments, updated with the following changes:

  • remove bitfield variable instance and use dev->name for logging
  • assign .mac_addr using macro DT_INST_PROP_OR()
  • move DT_INST_FOREACH_STATUS_OKAY to the end and use it only once
  • remove init_done from the initialize procedure
  • PHY connection type: add multi instances support, remove build assert check (errors reported at runtime)
  • add multi instances support for MAC address

#define GMAC_QUEUE_NUM DT_INST_PROP(0, num_queues) in the header file not changed. Currently, we assume that the queue numbers of all instances are the same, otherwise the code and macros related to GMAC_QUEUE_NUM need to be updated. The code and macros are also be affected by some parameters come from CONFIG_. It's too complicated to put them in one pull request.

@TonyHan11 TonyHan11 force-pushed the gmac_multi_instance branch from 2f68375 to a6537c6 Compare June 5, 2025 09:22
@TonyHan11
Copy link
Contributor Author

Rebased on the latest main branch to pick up the CI error workaround.

Comment on lines 2099 to 2101
(COND_CODE_1(DT_NODE_HAS_PROP(DT_DRV_INST(n), local_mac_address), \
(MAC_ADDR_SOURCE_LOCAL), \
(MAC_ADDR_SOURCE_INVALID))))))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to check for local address, also a invalid mac address should not stop the init as the user can change it later via the api.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, remove them and only handle mac_eeprom and zephyr_random_mac_address cases.
Updated, thanks a lot.


#if DT_INST_NODE_HAS_PROP(0, mac_eeprom)
static void get_mac_addr_from_i2c_eeprom(uint8_t mac_addr[6])
static void get_mac_addr_from_i2c_eeprom(uint8_t mac_addr[6], const struct i2c_dt_spec i2c)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this part documented in the datasheet or other documentation of the soc manufacturer?
If not it should be removed, as it's up to the user to to set the mac later f.e. via the set_config api.

Also having ETH_SAM_GMAC_MAC_I2C_INT_ADDRESS and ETH_SAM_GMAC_MAC_I2C_INT_ADDRESS_SIZE as a Kconfig is not a good idea, as it can this way only be set for all instances at one, so for every instance another eeprom has to be used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting MAC address is not a part of the datasheet or documents for the soc.
The consideration of keeping the function here is mainly for compatible with the code without applying this patch.

ETH_SAM_GMAC_MAC_I2C_INT_ADDRESS and ETH_SAM_GMAC_MAC_I2C_INT_ADDRESS are used for all the instance which has mac-eeprom. It assumes that all the instances get MAC address starting at the same EEPROM offset address. The MAC address could be different for each instance with dts like bellow:

&gmac0 {
	mac-eeprom = <&eeprom0>;
	...
};
&gmac1 {
	mac-eeprom = <&eeprom1>;
	...
};

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it's not documented in a datasheet or a document for the soc, it should be removed, we had a similar case here
#87953 (comment)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, updated with the following:

  • remove the getting MAC address from EEPROM from the GMAC driver
  • remove the related configurations, properties from defconfig, device tree and yaml
  • use zephyr,random-mac-address; for MAC address initialize

@TonyHan11 TonyHan11 force-pushed the gmac_multi_instance branch 2 times, most recently from dd166f8 to 69c7a1f Compare June 9, 2025 03:02
@github-actions github-actions bot requested review from kartben and nashif June 9, 2025 03:03
@TonyHan11 TonyHan11 force-pushed the gmac_multi_instance branch from 69c7a1f to 0bf5ef1 Compare June 9, 2025 03:31
#if DT_INST_NODE_HAS_PROP(0, mac_eeprom)
get_mac_addr_from_i2c_eeprom(mac_addr);
#elif DT_INST_PROP(0, zephyr_random_mac_address)
#if DT_INST_PROP(0, zephyr_random_mac_address)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @TonyHan11 ,

I want to continue to use the eeprom mac address and I don't want to use an random mac.
What is the alternative ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setting the mac during runtime directly via 'set_config' or the 'net_mgmt' api

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What sample do that ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static int set_mac_addr(struct net_if *iface, uint8_t *mac_addr)
{
    if (iface == NULL) {
        LOG_ERR("No interface configured");
        return -EINVAL;
    }
    struct ethernet_req_params params = {0};

    memcpy(params.mac_address.addr, mac_addr, 6);

    net_if_down(iface);

    int ret = net_mgmt(NET_REQUEST_ETHERNET_SET_MAC_ADDRESS, iface, &params,
               sizeof(struct ethernet_req_params));
    if (ret < 0) {
        LOG_ERR("changing mac address failed with error code %d", ret);
        goto set_mac_addr_end;
    }

    ret = memcmp(net_if_get_link_addr(iface)->addr, mac_addr, sizeof(params.mac_address.addr));
    if (ret != 0) {
        LOG_ERR("changing mac address failed - set mac not equal to provided mac %d", ret);
        ret = -1;
        goto set_mac_addr_end;
    }
    LOG_DBG("MAC address changed to %02x:%02x:%02x:%02x:%02x:%02x",
        mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);

set_mac_addr_end:
    net_if_up(iface);

    return ret;
}

We use this before using dhcp, so with a SYS_INIT with prio 94

I don't remember a sample, that shows that

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember a sample, that shows that

It is because we don't have this in Zephyr yet and here the driver do the bootstrap to the user.

I think what you mention is a great candidate to be automatically applied based on configuration, for instance:

(1) local-mac-address from devicetree
(2) Random address
(3) Eeprom address
(4) None

The network management could do this to the user as a bootstrap and then we can remove this from the driver. User still have the power to complete skip when no option is provided.

In my case, I need to test sometimes on many boards and it is unacceptable to me change ip address each time I change a board. Problems could happen if the random MAC is the same between boards.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

only these sources for mac addresses should be in a ethernet driver:

  1. local-mac-address from devicetree
  2. random address
  3. a kind of unique address generated via HWINFO
  4. If specified and documented by the manufacturer other sources like special registers or fuses (user programmable or set by the manufacture)

For production devices you are supposed to use the api to set the mac address, if 4 is not available.

Adding other generic methods into the drivers would lead to duplicated code and makes the drivers more messy and less maintainable.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @maass-hamburg,

I think we want the same. I'm fine with your comments but I want a solution to use the EEPROM which user don't need to act. The implementation is on this driver for years and there is no current proposal to solve what you don't like, which is fine.

So, when a viable proposal is defined the EEPROM read can be removed from the driver otherwise it should be kept.

NOTE: User can chose to not have Network Management and this imply that solution should be inside the driver somehow. One possible proposal is create a some hook mechanism that allows a generic way to apply the EEPROM MAC to any platform or anything else. HWINFO should not be a mandatory dependency to solve this. Inclusive, a hook could even use the HWINFO and this do not need to be inside the driver.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, then let's deprecate CONFIG_ETH_SAM_GMAC_MAC_I2C_EEPROM (add a select DEPRECATED) and only make the dt prop mac-eeprom work, when there is only one activated instance. ( a build assert with !(DT_ANY_INST_HAS_PROP_STATUS_OKAY(mac_eeprom) && ( DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) > 1)))

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated with the following:

  • revert the code related with mac-eeprom
  • add deprecated to mac-eeprom and ETH_SAM_GMAC_MAC_I2C_EEPROM
  • add BUILD_ASSERT to limited mac-eeprom be used when there's only one activated GMAC instance

@TonyHan11 TonyHan11 force-pushed the gmac_multi_instance branch 2 times, most recently from d04c0e2 to 75008f4 Compare June 12, 2025 02:16
@TonyHan11
Copy link
Contributor Author

@maass-hamburg a commit added for supporting zephyr,random-mac-address for each GMAC instance. Thank you very much.

Copy link
Member

@maass-hamburg maass-hamburg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might also be good to have a board in tree, that has more than one GMAC instance, so it can be tested

.phy_dev = DEVICE_DT_GET(DT_INST_PHANDLE(n, phy_handle)), \
.num_queues = DT_INST_PROP(n, num_queues), \
.phy_conn_type = DT_INST_ENUM_IDX(n, phy_connection_type), \
.random_mac_addr = SAM_GMAC_RANDOM_MAC_ADDR(n), \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.random_mac_addr = SAM_GMAC_RANDOM_MAC_ADDR(n), \
.random_mac_addr = DT_INST_PROP(n, zephyr_random_mac_address), \

COND_CODE_1 is not needed

#define PRIORITY_QUEUE1_RX_DESC_COUNT 1
#define PRIORITY_QUEUE1_TX_DESC_COUNT 1
#endif
#define PRIORITY_QUEUE_RX_DESC_COUNT \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line 34:

#define GMAC_QUEUE_NUM DT_INST_PROP(0, num_queues)

still depends on the first instance

#define SAM_GMAC_IRQ_CONFIG_DEFN(n) \
static void eth##n##_irq_config(void) \
{ \
DEFN_IRQ_CONFIG_0(n) \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can probably use something like DT_INST_FOREACH_PROP_ELEM() to iterate over the interrupts or interrupt-names. (Also use DT_INST_IRQN_BY_IDX()) Also looks like num-queues is just the amount of interrupts, if thats the case num-queues` is redundant and should be removed.

@TonyHan11 TonyHan11 force-pushed the gmac_multi_instance branch from c06bf2c to b77ecb3 Compare June 26, 2025 08:26
@TonyHan11
Copy link
Contributor Author

@maass-hamburg Many thanks for your comments.

As there's only one GMAC on each SOC currently supported, no more instances is added. For the next supported SOC (SAMA7G5), it has 2 GMACs. The support for SAMA7G5 GMAC will be added based on this PR.

Updated with the following:

  • add multi-instance support for max-frame-size property
  • COND_CODE_1(DT_INST_PROP(n, zephyr_random_mac_address), (true), (false)): unuse COND_CODE_1
  • #define GMAC_QUEUE_NUM DT_INST_PROP(0, num_queues)
    As there will be a big change for applying the corresponding num-queues for each GMAC struct eth_sam_dev_data, here just keep it as is. Adding a BUITD_ASSERT in the last commit to make sure the array queue_list[] is large enough for all GMAC instances.
    GMAC_QUEUE_NUM is a value of num-queues for the first GMAC instance getting from the device tree. It is used directly or indirectly (by GMAC_PRIORITY_QUEUE_NUM) for defining and initializing struct eth_sam_dev_data with a value from Kconfig (GMAC_ACTIVE_PRIORITY_QUEUE_NUM).

The same as GMAC_QUEUE_NUM, there are many configurations in Kconfig.sam_gmac which are used for all the GMAC instances. Might it is better to adapt them for multi-instance support or move them to the device tree in the future.

can probably use something like DT_INST_FOREACH_PROP_ELEM() to iterate over the interrupts or interrupt-names. (Also use DT_INST_IRQN_BY_IDX()) Also looks like num-queues is just the amount of interrupts, if thats the case num-queues` is redundant and should be removed.

Same as the above, conditional code controlled by both variables from DT and Kconfig, not easy to use macros to simplify it.

@sonarqubecloud
Copy link

@maass-hamburg
Copy link
Member

@TonyHan11 how about you bring in (limited) support for SAMA7G5 with only one Ethernet controller in the device tree in a separate PR and then add the second controller in this PR. You probably already have this local, as you have to test this code, if it really works for multiple instances.

@TonyHan11
Copy link
Contributor Author

@TonyHan11 how about you bring in (limited) support for SAMA7G5 with only one Ethernet controller in the device tree in a separate PR and then add the second controller in this PR. You probably already have this local, as you have to test this code, if it really works for multiple instances.

The GMAC support for SAMA7G5 on local depends on the GPIO drivers. I'll create the PR after GPIO is ready.

@github-actions
Copy link

This pull request has been marked as stale because it has been open (more than) 60 days with no activity. Remove the stale label or add a comment saying that you would like to have the label removed otherwise this pull request will automatically be closed in 14 days. Note, that you can always re-open a closed pull request at any time.

@github-actions github-actions bot added the Stale label Aug 27, 2025
@nandojve
Copy link
Member

Hi @TonyHan11 ,

@TonyHan11 how about you bring in (limited) support for SAMA7G5 with only one Ethernet controller in the device tree in a separate PR and then add the second controller in this PR. You probably already have this local, as you have to test this code, if it really works for multiple instances.

The GMAC support for SAMA7G5 on local depends on the GPIO drivers. I'll create the PR after GPIO is ready.

DId you create the PR ? If yes, could you CC the reference ?

@github-actions github-actions bot removed the Stale label Aug 29, 2025
@TonyHan11
Copy link
Contributor Author

Hi @TonyHan11 ,

@TonyHan11 how about you bring in (limited) support for SAMA7G5 with only one Ethernet controller in the device tree in a separate PR and then add the second controller in this PR. You probably already have this local, as you have to test this code, if it really works for multiple instances.

The GMAC support for SAMA7G5 on local depends on the GPIO drivers. I'll create the PR after GPIO is ready.

DId you create the PR ? If yes, could you CC the reference ?

PR #95135 is created for supporting SAMA7G5 GMAC1, thanks.

@nandojve
Copy link
Member

needs rebase

@nandojve
Copy link
Member

ping @TonyHan11

@nandojve nandojve added this to the v4.4.0 milestone Oct 25, 2025
The lists optimized includes:
 - RX descriptors list
 - TX descriptors list
 - RX buffer accounting list
 - TX buffer accounting list
 - TX frames accounting list

Signed-off-by: Tony Han <[email protected]>
Changes includes:
 - add the variable for num_queues to eth_sam_dev_cfg
 - update LOG with dev->name to distinguish different instances

Signed-off-by: Tony Han <[email protected]>
Change the driver from support 1 instance to support multi instances.

Changes includes:
 - irq_config()
 - config & data definitions
 - ETH_NET_DEVICE_DT_INST_DEFINE
 - PTP content / init / DEVICE_DEFINE

Limitations:
 - generate_mac() to be updated for supporting multi instances.
 - the configurations in Kconfig.sam_gmac are used for all instances.

Signed-off-by: Tony Han <[email protected]>
Add variable "max_frame_size" to get and use the max-frame-size from
DT for different GMAC instances.

Signed-off-by: Tony Han <[email protected]>
Add variable "phy_conn_type" to get and use the phy_connection_type from
DT for different GMAC instances.
Update the judgement on phy_connection_type for multi instances support.

Signed-off-by: Tony Han <[email protected]>
To allow every interface be initialized properly when there are more than
one instance, remove the static variable "init_done" which is used to make
the initialize procedure only be done once.

Signed-off-by: Tony Han <[email protected]>
Deprecate the 'ETH_SAM_GMAC_MAC_I2C_EEPROM' for the 'mac-eeprom' option,
Limite it to be used when there's only one activated GMAC instance.

Signed-off-by: Tony Han <[email protected]>
Add variable 'random_mac_addr' for 'zephyr,random-mac-address' from
device tree. Update generate_mac() to get random MAC address for each
GAMC interface with the 'zephyr,random-mac-address' property.

Signed-off-by: Tony Han <[email protected]>
'GMAC_QUEUE_NUM' is a value of 'num-queues' for the first GMAC
instance getting from the device tree. It is used directly or
indirectly (by GMAC_PRIORITY_QUEUE_NUM) for defining and
initializing 'struct eth_sam_dev_data' with a value from Kconfig
(GMAC_ACTIVE_PRIORITY_QUEUE_NUM).

As there will be a big change for applying the corresponding
num-queues for each GMAC 'struct eth_sam_dev_data', here just
keep it as is. Adding the BUITD_ASSERT to make sure the array
queue_list[] is large enough for all GMAC instances.

Signed-off-by: Tony Han <[email protected]>
@sonarqubecloud
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants